package beautiful.butterfly.drds.binlog.netty.server;

import beautiful.butterfly.drds.binlog.handlers.ServiceChannelInitializer;
import beautiful.butterfly.drds.binlog.utils.PropertiesExtend;
import beautiful.butterfly.drds.binlog.utils.TimeUtils;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;

@Slf4j
public class NettyServer
{
    //cpu
    private static int availableProcessors = Runtime.getRuntime().availableProcessors();
    private static CountDownLatch countDownLatch = new CountDownLatch(1);

    static
    {
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                PropertiesExtend p = PropertiesExtend.getInstance();
                int port = p.getNettyPort();
                int boss = p.getNettyBoss();
                int worker = p.getNettyWorker();
                log.error("cpu:" + availableProcessors + " port:" + port + " boss:" + boss + " worker:" + worker);
                EventLoopGroup bossGroup = new NioEventLoopGroup(boss);
                // 这里要做一些变动，使用自己的类，方便干预一些行为
                EventLoopGroup workerGroup = new NioEventLoopGroup(worker);
                try
                {
                    ServerBootstrap b = new ServerBootstrap();
                    b.group(bossGroup, workerGroup).channel(MyNioServerSocketChannel.class)
                            .option(ChannelOption.SO_BACKLOG, 1024)//
                            .childOption(ChannelOption.SO_RCVBUF, 10485760)//
                            .childOption(ChannelOption.SO_SNDBUF, 10485760)//
                            .childOption(ChannelOption.TCP_NODELAY, true)//
                            .childOption(ChannelOption.SO_REUSEADDR, true) // //重用地址
                            .childOption(ChannelOption.SO_KEEPALIVE, true)//
                            .childHandler(new ServiceChannelInitializer());
                    // 绑定端口，同步等待成功
                    ChannelFuture f = b.bind(port).sync();
                    // 等待服务端监听端口关闭
                    countDownLatch.countDown();
                    f.channel().closeFuture().sync();
                } catch (Exception e)
                {
                    log.error(e.getMessage());
                } finally
                {// 优雅退出，释放线程资源
                    bossGroup.shutdownGracefully();
                    workerGroup.shutdownGracefully();
                    System.exit(-1);// netty都不在了，退出吧
                    log.error("Netty Server exit...");
                }
            }
        }).start();
    }

    public synchronized static void start()
    {
        // 仅仅为了启动netty 线程,保证只会启动1次
        while (true)
        {
            try
            {
                countDownLatch.await();
                break;
            } catch (InterruptedException e)
            {
                log.error(e.toString());
                TimeUtils.sleepMilliSeconds(100);
                continue;
            }
        }
        log.error("netty server start ok.");
    }
}
